#include "SceneLoader.h"

SceneLoader::SceneLoader(string fd){
	textureID=4;
	filename=fd;
}

int SceneLoader::getNextTexID(){
	return ++textureID;
}

bool SceneLoader::init(){
	bool b;
	b=readFile();
	b=validateFile();
	if(b) b=readFile();
	//if(b) b=loadViews();
	if(b) b=loadIllumination();
	//if(b) b=loadLights();
	if(b) b=loadTextures();
	if(b) b=loadMaterials();
	if(b) b=loadTransformations();
	if(b) b=loadPrimitives();
	if(b) b=loadComponents();
	if(b) b=parseComponents();
	if(b) b=loadScene();
	return b;
}

bool SceneLoader::readFile(){
	doc = TiXmlDocument(filename.c_str());
	bool loadOkay = doc.LoadFile();	
	return loadOkay;
}

bool SceneLoader::loadPrimitives(){
	TiXmlElement *_primitives = doc.RootElement()->FirstChildElement( "primitives" );

	bool got=false;
	Primitive* pri; 
	Material* mat; 
	Texture* tex;

	for(TiXmlElement *elem(_primitives->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "primitive")
		{
			string primitive = elem->Attribute("id");
			
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "material"){
					string mmat = subelem->Attribute("id");
					mat = getMaterial(mmat);
					if(mat == NULL){
						printf("referenced material not found: %s\n",mmat.c_str());
						return false;
					}
				}
				else if(subelem->ValueTStr() == "texture"){
					string mtex = subelem->Attribute("id");
					tex = getTexture(mtex);
					if(tex == NULL){
						printf("referenced texture not found: %s\n",mtex.c_str());
						return false;
					}
				}
				else if(subelem->ValueTStr() == "rectangle"){
					
						float x1,y1,x2,y2;
						subelem->QueryFloatAttribute("x1",&x1);
						subelem->QueryFloatAttribute("y1",&y1);
						subelem->QueryFloatAttribute("x2",&x2);
						subelem->QueryFloatAttribute("y2",&y2);

						pri = new RectangleP(x1,y1,x2,y2,mat,tex);
						got=true;
					
				}
				else if(subelem->ValueTStr() == "triangle"){
					
						float x1,x2,x3,y1,y2,y3,z1,z2,z3;
						subelem->QueryFloatAttribute("x1",&x1);
						subelem->QueryFloatAttribute("y1",&y1);
						subelem->QueryFloatAttribute("x2",&x2);
						subelem->QueryFloatAttribute("y2",&y2);
						subelem->QueryFloatAttribute("x3",&x3);
						subelem->QueryFloatAttribute("y3",&y3);
						subelem->QueryFloatAttribute("z1",&z1);
						subelem->QueryFloatAttribute("z2",&z2);
						subelem->QueryFloatAttribute("z3",&z3);
						
						pri = new TriangleP(x1,x2,x3,y1,y2,y3,z1,z2,z3,mat,tex);
						got=true;
				} 
				else if(subelem->ValueTStr() == "cylinder"){
				
						float base,top,height; int slices,stacks;
						subelem->QueryFloatAttribute("base",&base);
						subelem->QueryFloatAttribute("top",&top);
						subelem->QueryFloatAttribute("height",&height);
						subelem->QueryIntAttribute("slices",&slices);
						subelem->QueryIntAttribute("stacks",&stacks);

						pri= new CylinderP(base,top,height,slices,stacks,mat,tex);
						got=true;
						
				}
				else if(subelem->ValueTStr() == "torus"){
					
						float inner,outer; int slices, loops;

						subelem->QueryFloatAttribute("inner",&inner);
						subelem->QueryFloatAttribute("outer",&outer);
						subelem->QueryIntAttribute("slices",&slices);
						subelem->QueryIntAttribute("loops",&loops);
						
						pri= new TorusP(inner,outer,slices,loops,mat,tex);
						got=true;
				} 
				else if(subelem->ValueTStr() == "sphere"){

					float radius; int slices, stacks;

					subelem->QueryFloatAttribute("radius",&radius);
					subelem->QueryIntAttribute("stacks",&stacks);
					subelem->QueryIntAttribute("slices",&slices);
									
					pri = new SphereP(radius,stacks,slices,mat,tex);
					got=true;
				}

				if(got)
					primitives[primitive]=pri;

				got=false;
			}
		}
	}
	return true;
}

bool isBool(TiXmlElement *elem, string name){
	 int a;
	 if (elem->QueryIntAttribute(name.c_str(),&a) != TIXML_SUCCESS)
		 return false;
	 else
		 return (a==1 || a==0);
}

int countAttr(TiXmlElement *elems){
	int i=0;
	for(TiXmlAttribute *atr(elems->FirstAttribute()); atr != NULL; atr = atr->Next())
		++i;
	return i;
}

bool SceneLoader::validateFile()
{
	string error= "invalid dsx";
	int *istub; float* fstub=new float();string sstring;
	TiXmlElement *_root,*_scene,*_views,*_illumination,*_lights,*_textures,*_materials,*_transformations,*_primitives,*_components;

	_root = doc.RootElement();	 
	if(_root == NULL || _root->ValueTStr() !="dsx" || countAttr(_root)!=0)
	{  printf("%s",error.c_str());return false; }

	//----------------------------------------------------------------------------------------------------------
	error="scene";
	_scene = _root->FirstChildElement( "scene" );
	if(_scene==NULL || _scene->Attribute("root") == NULL 
		|| _scene->QueryFloatAttribute("axis_length",fstub) != TIXML_SUCCESS || countAttr(_scene)!=2)
	{  printf("%s",error.c_str());return false; }

	//----------------------------------------------------------------------------------------------------------
	error="views";
	bool foundEnough=false;
	_views = _root->FirstChildElement( "views" );
	if(_views==NULL || _views->Attribute("default") == NULL || countAttr(_views)!=1)
	{  printf("%s",error.c_str()); return false;}
	for(TiXmlElement *elem(_views->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{
		if( elem->ValueTStr() == "perspective")
		{
			if(elem->Attribute("id") == NULL ||
				elem->QueryFloatAttribute("near",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("far",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("angle",fstub) != TIXML_SUCCESS || countAttr(elem)!=4)
			{ printf("%s",error.c_str()); return false;  }

			bool ffrom=false, fto=false;
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "from"){
					if( ffrom ||
						subelem->QueryFloatAttribute("x",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z",fstub) != TIXML_SUCCESS || countAttr(subelem)!=3)
					{ printf("%s",error.c_str()); return false;  }
					ffrom=true;
				}
				else if (subelem->ValueTStr() == "to"){
					if( fto ||
						subelem->QueryFloatAttribute("x",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z",fstub) != TIXML_SUCCESS || countAttr(subelem)!=3)
					{ printf("%s",error.c_str()); return false;  }
					fto=true;
				}
				else
				{
					{ printf("%s",error.c_str()); return false;  }
				} 
			} 
			if(!(ffrom && fto))
			{ printf("%s",error.c_str()); return false;  }
			foundEnough=true;
		} 
		else if(elem->ValueTStr() == "ortho")
		{
			if( elem->Attribute("id") == NULL ||
				elem->QueryFloatAttribute("near",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("far",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("left",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("right",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("top",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("bottom",fstub) != TIXML_SUCCESS || countAttr(elem)!=7)
			{ printf("%s",error.c_str()); return false;  }
			foundEnough=true;
		}
		else 
		{
			{ printf("%s",error.c_str()); return false;  }
		}
	}
	if(!foundEnough)
	{ printf("%s",error.c_str()); return false;  }

	//----------------------------------------------------------------------------------------------------------
	error="illumination";
	_illumination = _root->FirstChildElement( "illumination" );
	if(_illumination==NULL || !isBool(_illumination,"doublesided") || !isBool(_illumination,"local") || countAttr(_illumination)!=2)
	{ printf("%s",error.c_str()); return false;  }
	bool fambient=false,fbackground=false;
	for(TiXmlElement *elem(_illumination->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "ambient")
		{
			if( fambient ||
				elem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(elem)!=4)
			{ printf("%s",error.c_str()); return false;  }
			fambient=true;
		}
		else if( elem->ValueTStr() == "background")
		{
			if( fbackground ||
				elem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(elem)!=4)
			{ printf("%s",error.c_str()); return false;  }
			fbackground=true;
		}
		else 
		{
			{ printf("%s",error); return false;  }
		}
	}
	if(!(fambient && fbackground))
	{ printf("%s",error); return false;  }
	//----------------------------------------------------------------------------------------------------------
	error="lights";
	int lcounter=0;
	_lights = _root->FirstChildElement( "lights" );
	if(_lights==NULL  || countAttr(_root)!=0)
	{ printf("%s",error.c_str()); return false;  }
	foundEnough=false;
	for(TiXmlElement *elem(_lights->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "omni")
		{
			if(++lcounter > 7) { printf("Number of lights highter then 7"); return false;  }
			if(elem->Attribute("id") == NULL || !isBool(elem,"enabled")  || countAttr(elem)!=2)
			{ printf("%s",error.c_str()); return false;  }
			foundEnough=true;

			bool flocation=false, fdiffuse=false,fambient=false, fspecular=false;
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "location"){
					if( flocation ||
						subelem->QueryFloatAttribute("x",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("w",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					flocation=true;
				}
				else if (subelem->ValueTStr() == "ambient"){
					if( fambient ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					fambient=true;
				}
				else if (subelem->ValueTStr() == "diffuse"){
					if( fdiffuse ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					fdiffuse=true;
				}
				else if (subelem->ValueTStr() == "specular"){
					if( fspecular ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					fspecular=true;
				}
				else
				{
					{ printf("%s",error.c_str()); return false;  }
				} 
			}
			if(!(flocation && fdiffuse  && fambient && fspecular))
			{ printf("%s",error.c_str()); return false;  }

		}
		else if( elem->ValueTStr() == "spot"){

			if(++lcounter > 8) { printf("Number of lights highter then 8"); return false;  }

			if(elem->Attribute("id") == NULL ||
				!isBool(elem,"enabled") || 
				elem->QueryFloatAttribute("angle",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("exponent",fstub) != TIXML_SUCCESS  || countAttr(elem)!=4)
			{ printf("%s",error.c_str()); return false;  }
			foundEnough=true;

			bool flocation=false, fdiffuse=false, fambient=false, fspecular=false, ftarget=false;
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "location"){
					if( flocation ||
						subelem->QueryFloatAttribute("x",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=3)
					{ printf("%s",error.c_str()); return false;  }
					flocation=true;
				}
				else if (subelem->ValueTStr() == "ambient"){
					if( fambient ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					fambient=true;
				}
				else if (subelem->ValueTStr() == "diffuse"){
					if( fdiffuse ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					fdiffuse=true;
				}
				else if (subelem->ValueTStr() == "specular"){
					if( fspecular ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					fspecular=true;
				}
				else if (subelem->ValueTStr() == "target"){
					if( ftarget ||
						subelem->QueryFloatAttribute("x",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z",fstub) != TIXML_SUCCESS || countAttr(subelem)!=3 )
					{ printf("%s",error.c_str()); return false;  }
					ftarget=true;
				}
				else
				{
					{ printf("%s",error.c_str()); return false;  }
				} 	  
			}
			if(!(flocation && fdiffuse && fambient && fspecular && ftarget))
			{ printf("%s",error.c_str()); return false;  }
		}

	}
	if(!foundEnough)
	{ printf("%s",error.c_str()); return false;  }

	//----------------------------------------------------------------------------------------------------------
	error="textures";
	_textures = _root->FirstChildElement( "textures" );
	if(_textures==NULL  || countAttr(_textures)!=0)
	{ printf("%s",error.c_str()); return false;  }
	foundEnough=false;

	for(TiXmlElement *elem(_textures->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "texture")
		{
			if( elem->Attribute("id") == NULL ||
				elem->Attribute("file") == NULL ||
				elem->QueryFloatAttribute("length_s",fstub) != TIXML_SUCCESS ||
				elem->QueryFloatAttribute("length_t",fstub) != TIXML_SUCCESS  || countAttr(elem)!=4)
			{ printf("%s",error.c_str()); return false;  }
			foundEnough=true;
		}
	}
	if(!foundEnough)
	{ printf("%s",error.c_str()); return false;  }

	//----------------------------------------------------------------------------------------------------------
	error="materials";
	_materials = _root->FirstChildElement( "materials" );
	if(_materials==NULL || countAttr(_materials)!=0)
	{ printf("%s",error.c_str()); return false;  }
	foundEnough=false;

	for(TiXmlElement *elem(_materials->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "material")
		{
			if(elem->Attribute("id") == NULL || countAttr(elem)!=1)
			{ printf("%s",error.c_str()); return false;  }
			foundEnough=true;

			bool femission=false, fambient=false, fdiffuse=false, fspecular=false, fshininess=false;
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "emission"){
					if( femission ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					femission=true;
				}
				else if (subelem->ValueTStr() == "ambient"){
					if( fambient ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					fambient=true;
				}
				else if (subelem->ValueTStr() == "diffuse"){
					if( fdiffuse ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					fdiffuse=true;
				}
				else if (subelem->ValueTStr() == "specular"){
					if( fspecular ||
						subelem->QueryFloatAttribute("r",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("g",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("b",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("a",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					fspecular=true;
				}
				else if (subelem->ValueTStr() == "shininess"){
					if( fshininess || 
						subelem->QueryFloatAttribute("value",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=1)
					{ printf("%s",error.c_str()); return false;  }
					fshininess=true;
				}
				else
				{
					{ printf("%s",error.c_str()); return false;  }
				}
			}
			if(!(femission && fambient && fdiffuse && fspecular && fshininess))
			{ printf("%s",error.c_str()); return false;  }
		}
	}
	if(!foundEnough)
	{ printf("%s",error.c_str()); return false;  }

	//----------------------------------------------------------------------------------------------------------
	error="transformations";
	_transformations = _root->FirstChildElement( "transformations" );
	if(_transformations==NULL || countAttr(_transformations)!=0)
	{ printf("%s",error.c_str()); return false;  }
	foundEnough=false; bool foundEnoughOuter=false;

	for(TiXmlElement *elem(_transformations->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "transformation")
		{
			if(elem->Attribute("id") == NULL || countAttr(elem)!=1)
			{ printf("%s",error.c_str()); return false;  }
			foundEnoughOuter=true;

			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "translate"){
					if( subelem->QueryFloatAttribute("x",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z",fstub) != TIXML_SUCCESS ||
						countAttr(subelem)!=3)
					{ printf("%s",error.c_str()); return false;  }
					foundEnough=true;
				} 
				else if(subelem->ValueTStr() == "rotate"){
					if( subelem->QueryFloatAttribute("angle",fstub) != TIXML_SUCCESS ||
						!((sstring=subelem->Attribute("axis")) == "x"  || 
						(sstring=subelem->Attribute("axis")) == "y"  || 
						(sstring=subelem->Attribute("axis")) == "z") ||
						countAttr(subelem)!=2)
					{ printf("%s",error.c_str()); return false;  }
					foundEnough=true;
				}
				else if(subelem->ValueTStr() == "scale"){
					if( subelem->QueryFloatAttribute("x",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z",fstub) != TIXML_SUCCESS ||
						countAttr(subelem)!=3)
					{ printf("%s",error.c_str()); return false;  }
					foundEnough=true;
				}
				else
				{
					{ printf("%s",error.c_str()); return false;  }
				}
			}
			if(!foundEnough)
			{ printf("%s",error.c_str()); return false;  }
		}
	}
	if(!foundEnoughOuter)
	{ printf("%s",error.c_str()); return false;  }
	//----------------------------------------------------------------------------------------------------------
	error="primitives";
	_primitives = _root->FirstChildElement( "primitives" );
	if(_primitives==NULL || countAttr(_primitives)!=0)
	{ printf("%s",error.c_str()); return false;  }
	foundEnough=false;

	for(TiXmlElement *elem(_primitives->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "primitive")
		{
			if(elem->Attribute("id") == NULL || countAttr(elem)!=1)
			{ printf("%s",error.c_str()); return false;  }
			foundEnough=true;

			bool fmaterial=false,ftexture=false,ftype=false;
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "material"){
					if( fmaterial || subelem->Attribute("id") == NULL || countAttr(subelem)!=1)
					{ printf("%s",error.c_str()); return false;  }
					fmaterial=true;
				}
				else if(subelem->ValueTStr() == "texture"){
					if( ftexture || subelem->Attribute("id") == NULL || countAttr(subelem)!=1)
					{ printf("%s",error.c_str()); return false;  }
					ftexture=true;
				}
				else if(subelem->ValueTStr() == "rectangle"){
					if( ftype ||
						subelem->QueryFloatAttribute("x1",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y1",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("x2",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y2",fstub) != TIXML_SUCCESS  || countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					ftype=true;
				}
				else if(subelem->ValueTStr() == "triangle"){
					if( ftype ||
						subelem->QueryFloatAttribute("x1",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y1",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("x2",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y2",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("x3",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("y3",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z1",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z2",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("z3",fstub) != TIXML_SUCCESS || 
						countAttr(subelem)!=9)
					{ printf("%s",error.c_str()); return false;  }
					ftype=true;
				} 
				else if(subelem->ValueTStr() == "cylinder"){
					if( ftype ||
						subelem->QueryFloatAttribute("base",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("top",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("height",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("slices",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("stacks",fstub) != TIXML_SUCCESS || 
						countAttr(subelem)!=5)
					{ printf("%s",error.c_str()); return false;  }
					ftype=true;
				}
				else if(subelem->ValueTStr() == "torus"){
					if( ftype ||
						subelem->QueryFloatAttribute("inner",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("outer",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("slices",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("loops",fstub) != TIXML_SUCCESS ||
						countAttr(subelem)!=4)
					{ printf("%s",error.c_str()); return false;  }
					ftype=true;
				}
				else if(subelem->ValueTStr() == "sphere"){
					if( ftype ||
						subelem->QueryFloatAttribute("radius",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("slices",fstub) != TIXML_SUCCESS ||
						subelem->QueryFloatAttribute("stacks",fstub) != TIXML_SUCCESS ||
						countAttr(subelem)!=3)
					{ printf("%s",error.c_str()); return false;  }
					ftype=true;
				}
				else
				{
					{ printf("%s",error.c_str()); return false;  }
				}
			}
			if(!(fmaterial && ftexture && ftype))
			{ printf("%s",error.c_str()); return false;  }
			fmaterial=ftexture=ftype=false;
		}
	}
	if(!foundEnough)
	{ printf("%s",error.c_str()); return false;  }

	//----------------------------------------------------------------------------------------------------------
	error="components";
	_components = _root->FirstChildElement( "components" );
	if(_components==NULL || countAttr(_components)!=0)
	{ printf("%s",error.c_str()); return false;  }
	foundEnough=false;
	bool ftexture=false, fchildren=false, fmaterial=false,ftransformation=false;
	for(TiXmlElement *supelem(_components->FirstChildElement()); supelem != NULL; supelem = supelem->NextSiblingElement())
	{
		ftransformation=fmaterial=fchildren=ftexture=false;
		if( supelem->ValueTStr() == "component" && supelem->Attribute("id") != NULL && countAttr(supelem)==1)
		{

			for(TiXmlElement *elem(supelem->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
			{

				if( elem->ValueTStr() == "transformation" && countAttr(elem)==0)
				{
					if(ftransformation)
					{ printf("%s",error.c_str()); return false;  }
					bool ftransformation1=false;
					for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
					{
						if(subelem->ValueTStr() == "transformationref"){
							if( ftransformation || subelem->Attribute("id") == NULL || countAttr(subelem)!=1)
							{ printf("%s",error.c_str()); return false;  }
							ftransformation1=true;
							ftransformation=true;
						}
						else  if(subelem->ValueTStr() == "translate"){
							if( ftransformation1 ||
								subelem->QueryFloatAttribute("x",fstub) != TIXML_SUCCESS ||
								subelem->QueryFloatAttribute("y",fstub) != TIXML_SUCCESS ||
								subelem->QueryFloatAttribute("z",fstub) != TIXML_SUCCESS ||
								countAttr(subelem)!=3)
							{ printf("%s",error.c_str()); return false;  }
							ftransformation=true;
						} 
						else if(subelem->ValueTStr() == "rotate"){
							if( ftransformation1 ||
								subelem->QueryFloatAttribute("angle",fstub) != TIXML_SUCCESS ||
								!((sstring=subelem->Attribute("axis")) == "x"  || 
								(sstring=subelem->Attribute("axis")) == "y"  || 
								(sstring=subelem->Attribute("axis")) == "z") ||
								countAttr(subelem)!=2)
							{ printf("%s",error.c_str()); return false;  }
							ftransformation=true;
						}
						else if(subelem->ValueTStr() == "scale"){
							if( ftransformation1 ||
								subelem->QueryFloatAttribute("x",fstub) != TIXML_SUCCESS ||
								subelem->QueryFloatAttribute("y",fstub) != TIXML_SUCCESS ||
								subelem->QueryFloatAttribute("z",fstub) != TIXML_SUCCESS ||
								countAttr(subelem)!=3)
							{ printf("%s",error.c_str()); return false;  }
							ftransformation=true;
						}
						else
						{
							{ printf("%s on inline transformation",error.c_str()); return false;  }
						}
					}
				}
				else if( elem->ValueTStr() == "materials" && countAttr(elem)==0)
				{
					if(fmaterial)
					{ printf("%s",error.c_str()); return false;  }
					for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
					{
						if(subelem->ValueTStr() == "material"){
							if( fmaterial || subelem->Attribute("id") == NULL || countAttr(subelem)!=1)
							{ printf("%s",error.c_str()); return false;  }
							fmaterial=true;
						}
					}
				}
				else if( elem->ValueTStr() == "materials" && elem->Attribute("key") != NULL && countAttr(elem)==1)
				{
					if(fmaterial)
					{ printf("%s",error.c_str()); return false;  }
					int mats_found=0;
					for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
					{
						if(subelem->ValueTStr() == "material"){
							if(  subelem->Attribute("id") == NULL || countAttr(subelem)!=1)
							{ printf("%s",error.c_str()); return false;  }
							++mats_found;
							fmaterial=true;
						}
					}
					if(mats_found < 2)
					{ printf("%s",error.c_str()); return false;  }
				}
				else if( elem->ValueTStr() == "texture" && elem->Attribute("id") != NULL && countAttr(elem)==1){
					if(ftexture)
					{ printf("%s",error.c_str()); return false;  }
					ftexture=true;
				}
				else if( elem->ValueTStr() == "children" && countAttr(elem)==0){
					if(fchildren)
					{ printf("%s",error.c_str()); return false;  }
					for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
					{
						if(subelem->ValueTStr() == "componentref"){
							if(  subelem->Attribute("id") == NULL || countAttr(subelem)!=1)
							{ printf("%s",error.c_str()); return false;  }
							fchildren=true;

						}
						else if(subelem->ValueTStr() == "primitiveref"){
							if(  subelem->Attribute("id") == NULL || countAttr(subelem)!=1)
							{ printf("%s",error.c_str()); return false;  }
							fchildren=true;
						}
					}
				}
			}


		}
		else
		{
			{ printf("%s",error.c_str()); return false;  }
		}

		if(!(ftexture && fchildren && fmaterial /* && ftransformation*/))
		{ printf("%s",error.c_str()); return false;  }

	}


	return true;
}

Material* SceneLoader::getMaterial( string id )
{
	map<string,Material*>::iterator it = materials.find(id);

	if(it==materials.end())
		return NULL;
	else
		return it->second;
}

Texture* SceneLoader::getTexture( string id )
{
	map<string,Texture*>::iterator it = textures.find(id);

	if(it==textures.end())
		return NULL;
	else
		return it->second;
}


Primitive* SceneLoader::getPrimitive( string id )
{
	map<string,Primitive*>::iterator it = primitives.find(id);

	if(it==primitives.end())
		return NULL;
	else
		return it->second;
}

bool SceneLoader::loadTextures()
{
	TiXmlElement* _textures = doc.RootElement()->FirstChildElement( "textures" );
	
	for(TiXmlElement *elem(_textures->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "texture")
		{
			string texture = elem->Attribute("id"); 

			if(getTexture(texture) != NULL) //ID ja existe
			{
				printf("texture id already exists: %s\n",texture.c_str());
				return false;
			}
			const char * file = elem->Attribute("file");

			float length_s,length_t;
			elem->QueryFloatAttribute("length_s",&length_s);
			elem->QueryFloatAttribute("length_t",&length_t);
			
			Texture * tex = new Texture(file,getNextTexID(),length_s,length_t);
			textures[texture]=tex;
			
		}
	}

		//ADDING BASE CASES
		Texture * tex = new Texture(NULL,0,0,0,1);
		textures["inherit"]=tex;
		Texture * tex2 = new Texture(NULL,0,0,0,2);
		textures["none"]=tex2;

	return true;
}

bool SceneLoader::loadMaterials()
{
	TiXmlElement* _materials = doc.RootElement()->FirstChildElement( "materials" );

	for(TiXmlElement *elem(_materials->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "material")
		{
			string material = elem->Attribute("id");

			if(getMaterial(material) != NULL)
				{
				printf("material id already exists: %s\n",material.c_str());
				return false;
			}
			
			float mEmission[4],mAmbient[4],mDiffuse[4],mSpecular[4],mShininess[1];
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "emission"){
					
						subelem->QueryFloatAttribute("r",&mEmission[0]);
						subelem->QueryFloatAttribute("g",&mEmission[1]); 
						subelem->QueryFloatAttribute("b",&mEmission[2]); 
						subelem->QueryFloatAttribute("a",&mEmission[3]); 
					
				}
				else if (subelem->ValueTStr() == "ambient"){
				
						subelem->QueryFloatAttribute("r",&mAmbient[0]); 
						subelem->QueryFloatAttribute("g",&mAmbient[1]);
						subelem->QueryFloatAttribute("b",&mAmbient[2]); 
						subelem->QueryFloatAttribute("a",&mAmbient[3]); 
						
				}
				else if (subelem->ValueTStr() == "diffuse"){
				
						subelem->QueryFloatAttribute("r",&mDiffuse[0]);
						subelem->QueryFloatAttribute("g",&mDiffuse[1]); 
						subelem->QueryFloatAttribute("b",&mDiffuse[2]);
						subelem->QueryFloatAttribute("a",&mDiffuse[3]); 
					
				}
				else if (subelem->ValueTStr() == "specular"){
					
						subelem->QueryFloatAttribute("r",&mSpecular[0]); 
						subelem->QueryFloatAttribute("g",&mSpecular[1]); 
						subelem->QueryFloatAttribute("b",&mSpecular[2]);
						subelem->QueryFloatAttribute("a",&mSpecular[3]);
					
				}
				else if (subelem->ValueTStr() == "shininess"){
				
						subelem->QueryFloatAttribute("value",&mShininess[0]);
					
				}
			}

			Material *mat = new Material(mEmission,mAmbient,mDiffuse,mSpecular,mShininess);
			materials[material]=mat;
		}
	}

	Material *mat = new Material(NULL,NULL,NULL,NULL,NULL,1);
	materials["inherit"]=mat;


	return true;
}

bool SceneLoader::loadTransformations()
{
	
	TiXmlElement *_transformations = doc.RootElement()->FirstChildElement( "transformations" );
	vector<Transformation*> vTrans;

	for(TiXmlElement *elem(_transformations->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "transformation")
		{
			string transformation = elem->Attribute("id");
			vTrans.clear();	

			if(getTransformation(transformation) != NULL)
				{
				printf("transf id already exists: %s\n",transformation.c_str());
				return false;
			}

			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "translate"){

					float x,y,z;

					subelem->QueryFloatAttribute("x",&x);
					subelem->QueryFloatAttribute("y",&y); 
					subelem->QueryFloatAttribute("z",&z);
						
					Translate * trans = new Translate(x,y,z);
					vTrans.push_back(trans);
				} 
				else if(subelem->ValueTStr() == "rotate"){

					float angle; string axis;
					subelem->QueryFloatAttribute("angle",&angle);
					axis=subelem->Attribute("axis");

					Rotate *rot = new Rotate(axis,angle);
					vTrans.push_back(rot);	
				}
				else if(subelem->ValueTStr() == "scale"){

					float x,y,z;
					subelem->QueryFloatAttribute("x",&x);
					subelem->QueryFloatAttribute("y",&y); 
					subelem->QueryFloatAttribute("z",&z);

					Scale * sca = new Scale(x,y,z);
					vTrans.push_back(sca);
						
				}
				else
				{
					return false;
				}
			}

			Transformation * trsfm = new Transformation(vTrans);
			transformations[transformation]=trsfm;
		}
	}
		
	return true;
}

Transformation * SceneLoader::getTransformation( string id )
{
	map<string,Transformation*>::iterator it = transformations.find(id);

	if(it==transformations.end())
		return NULL;
	else
		return it->second;
}

bool SceneLoader::loadComponents()
{
	TiXmlElement *_components = doc.RootElement()->FirstChildElement("components");
	Transformation *mTransformation;
	vector<Material*> vecMat;
	string materialKEY="";
	unsigned char charKEY=NULL;
	Texture* mTex;
	vector<Primitive*> mPrimRef;
	vector<string> mCompRef;

	bool ftexture=false, fchildren=false, fmaterial=false,ftransformation=false;
	for(TiXmlElement *supelem(_components->FirstChildElement()); supelem != NULL; supelem = supelem->NextSiblingElement())
	{
		if( supelem->ValueTStr() == "component")
		{

			string componentID = supelem->Attribute("id"); 

			for(TiXmlElement *elem(supelem->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
			{

				if( elem->ValueTStr() == "transformation" && countAttr(elem)==0)
				{
					vector<Transformation*> vTrans;
					vTrans.clear();	
					Transformation* transf = NULL;

					for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
					{
						if(subelem->ValueTStr() == "transformationref"){
							string transRefID = subelem->Attribute("id");
							transf = getTransformation(transRefID);
							if(transf == NULL)
								{
									printf("referenced transformation not found: %s\n",transRefID.c_str());
									return false;
								}	
						}
						else  if(subelem->ValueTStr() == "translate"){

							float x,y,z;

							subelem->QueryFloatAttribute("x",&x);
							subelem->QueryFloatAttribute("y",&y); 
							subelem->QueryFloatAttribute("z",&z);

							Translate * trans = new Translate(x,y,z);
							vTrans.push_back(trans);
						} 
						else if(subelem->ValueTStr() == "rotate"){

							float angle; string axis;
							subelem->QueryFloatAttribute("angle",&angle);
							axis=subelem->Attribute("axis");

							Rotate *rot = new Rotate(axis,angle);
							vTrans.push_back(rot);	
						}
						else if(subelem->ValueTStr() == "scale"){

							float x,y,z;
							subelem->QueryFloatAttribute("x",&x);
							subelem->QueryFloatAttribute("y",&y); 
							subelem->QueryFloatAttribute("z",&z);

							Scale * sca = new Scale(x,y,z);
							vTrans.push_back(sca);

						}
						else
						{
							return false;
						}
					}

					if(transf != NULL)
					{
						mTransformation = transf;
					}
					else
					{
						mTransformation = new Transformation(vTrans);
					} 
				}
					
				else if( elem->ValueTStr() == "materials" && countAttr(elem)==0)
				{
					if(fmaterial)
						return false;
					for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
					{
						if(subelem->ValueTStr() == "material"){
							string materialID = subelem->Attribute("id");
							
							Material * mMaterial;
							if((mMaterial=getMaterial(materialID)) == NULL)
							{
								printf("referenced material not found: %s\n", materialID.c_str());
								return false;
							}
							vecMat.push_back(mMaterial);
						}
					}
				}
				else if( elem->ValueTStr() == "materials" && countAttr(elem)==1)
				{
					materialKEY = elem->Attribute("key");
					charKEY=materialKEY[0];

					if(materialKEY.length() > 1 || getMultMats(charKEY) != NULL  )
						{
						printf("referenced material not found: %s\n",materialKEY.c_str());
						return false;
					}
				
					
					for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
					{
						if(subelem->ValueTStr() == "material"){
							string matID=subelem->Attribute("id");

							Material *mat1;
							if((mat1=getMaterial(matID)) == NULL)
								return false;

							vecMat.push_back(mat1);							
						}

					}
					
				}
				else if( elem->ValueTStr() == "texture"  && countAttr(elem)==1){
					string textureID = elem->Attribute("id");
					if((mTex=getTexture(textureID)) == NULL)
						return false;
				}
				else if( elem->ValueTStr() == "children" && countAttr(elem)==0){
					

					for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
					{
						if(subelem->ValueTStr() == "componentref"){
							string compref = subelem->Attribute("id") ;
							mCompRef.push_back(compref);

						}
						else if(subelem->ValueTStr() == "primitiveref"){
							string primID = subelem->Attribute("id") ;

							Primitive * ppp;
							if((ppp=getPrimitive(primID)) == NULL)
								{
									printf("referenced primitive not found: %s\n",primID.c_str());
									return false;
								}

							mPrimRef.push_back(ppp);
						}
					}
				}
			}
			
			bool mult;
			if(vecMat.size()>1)
				mult=true;
			else
				mult=false;

			Component *compN = new Component(mPrimRef,vecMat,mTex,mTransformation, mult);

			tempComponents.push_back(compN);
			tempIDComponent.push_back(mCompRef);
			components[componentID]=compN;
			if(materialKEY != "")
				multMats[charKEY]=compN;
			mPrimRef.clear();
			mCompRef.clear();
			vecMat.clear();
			materialKEY="";
		}
		else
		{
			return false;
		}
	}

	return true;
}

Component* SceneLoader::getMultMats( char id )
{
	map< char,Component*>::iterator it = multMats.find(id);

	if(it==multMats.end())
		return NULL;
	else
		return it->second;
}

bool SceneLoader::parseComponents()
{
	for(int i=0; i<tempComponents.size(); ++i){
		vector<Component*> comps;
		comps.clear();
		for(int j=0; j<tempIDComponent[i].size(); ++j){
			Component* c;
			if((c=getComponent(tempIDComponent[i][j])) == NULL)
				{ printf("component id not found (parse): %s\n",tempIDComponent[i][j].c_str()); return false;  }
			else
				comps.push_back(c);
		}
		tempComponents[i]->setCompRef(comps);
		
	}

	tempComponents.clear();
	tempIDComponent.clear();

	return true;
}

Component* SceneLoader::getComponent( string id )
{
	map<string,Component*>::iterator it = components.find(id);

	if(it==components.end())
		return NULL;
	else
		return it->second;
}

void SceneLoader::cycleComponents()
{
	glPushMatrix();

	Component *root=getComponent(getSceneInfo()->getName());
	root->act(root->getTex()->getLengthS(),root->getTex()->getLengthT());

	glPopMatrix();
}

bool SceneLoader::loadScene()
{
	string main; int l;

	TiXmlElement *_scene = doc.RootElement()->FirstChildElement( "scene" );
	main = _scene->Attribute("root");

	if(getComponent(main) == NULL)
		return false;

	_scene->QueryIntAttribute("axis_length",&l);

	Scene *s= new Scene(main,l);
	setSceneInfo(s);
	
	return true;
}

Scene * SceneLoader::getSceneInfo()
{
	return sceneInfo;
}

void SceneLoader::setSceneInfo( Scene *s )
{
	sceneInfo=s;
}

bool SceneLoader::loadViews()
{
	TiXmlElement *_views = doc.RootElement()->FirstChildElement( "views" );
	
	string default_view= _views->Attribute("default");
	setCurrentViewID(default_view);
	float near,far,angle,fromX,fromY,fromZ,toX,toY,toZ,left,right,top,bottom;
	string viewID;
	for(TiXmlElement *elem(_views->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{
		if( elem->ValueTStr() == "perspective")
		{
				viewID = elem->Attribute("id");

				if(getMaterial(viewID)!=NULL)
				{
					printf("view id already exists: %s",viewID.c_str());
					return false;
				}

				elem->QueryFloatAttribute("near",&near);
				elem->QueryFloatAttribute("far",&far);
				elem->QueryFloatAttribute("angle",&angle);
				

		
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "from"){
					
						subelem->QueryFloatAttribute("x",&fromX);
						subelem->QueryFloatAttribute("y",&fromY);
						subelem->QueryFloatAttribute("z",&fromZ);
					
				}
				else if (subelem->ValueTStr() == "to"){
					
						subelem->QueryFloatAttribute("x",&toX); 
						subelem->QueryFloatAttribute("y",&toY); 
						subelem->QueryFloatAttribute("z",&toZ);
				
				}
				else
				{
					return false;
				} 
			} 

			Perspective * pers = new Perspective(near,far,angle,fromX,fromY,fromZ,toX,toY,toZ);
			views[viewID]=pers;
		} 
		else if(elem->ValueTStr() == "ortho")
		{
			viewID = elem->Attribute("id");

			if(getMaterial(viewID)!=NULL)
			{
				printf("view id already exists: %s",viewID.c_str());
				return false;
			}

			elem->QueryFloatAttribute("near",&near);
			elem->QueryFloatAttribute("far",&far);
			elem->QueryFloatAttribute("left",&left);
			elem->QueryFloatAttribute("right",&right); 
			elem->QueryFloatAttribute("top",&top); 
			elem->QueryFloatAttribute("bottom",&bottom); 
				
			Ortho * ort = new Ortho(near,far,left,right,top,bottom);
			views[viewID]=ort;
		}
		else 
		{
			return false;
		}
	}

	return true;
}

View * SceneLoader::getView( string id )
{
	map<string,View*>::iterator it = views.find(id);

	if(it==views.end())
		return NULL;
	else
		return it->second;
}

void SceneLoader::CurrentViewAct()
{
	View * v = getView(getCurrentViewID());
	if(v == NULL)
		exit(1);
	v->act();
}

void SceneLoader::setCurrentViewID(string d)
{
	currentView=d;
}

string SceneLoader::getCurrentViewID()
{
	return currentView;
}

bool SceneLoader::loadIllumination()
{
	TiXmlElement *_illumination = doc.RootElement()->FirstChildElement( "illumination" );

	int ds,local;
	float ar, ag,  ab,  aa,  rr,  rg,  rb,  ra;

	_illumination->QueryIntAttribute("doublesided",&ds);
	_illumination->QueryIntAttribute("local",&local);
	
	for(TiXmlElement *elem(_illumination->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "ambient")
		{
			
				elem->QueryFloatAttribute("r",&ar); 
				elem->QueryFloatAttribute("g",&ag);
				elem->QueryFloatAttribute("b",&ab); 
				elem->QueryFloatAttribute("a",&aa); 
		
		}
		else if( elem->ValueTStr() == "background")
		{
			
			elem->QueryFloatAttribute("r",&rr); 
			elem->QueryFloatAttribute("g",&rg);
			elem->QueryFloatAttribute("b",&rb); 
			elem->QueryFloatAttribute("a",&ra); 
		
		}
	}

	illumination = new Illumination(ar,ag,ab,aa,rr,rg,rb,ra,ds,local);
	illumination->act();

	return true;
}

Illumination* SceneLoader::getIllumination()
{
	return illumination;
}

bool SceneLoader::loadLights()
{
	TiXmlElement *_lights = doc.RootElement()->FirstChildElement( "lights" );

	int lightX=0;
	float ambient[4],diffuse[4],specular[4];
	int on;
	
	for(TiXmlElement *elem(_lights->FirstChildElement()); elem != NULL; elem = elem->NextSiblingElement())
	{

		if( elem->ValueTStr() == "omni")
		{
			string lightid = elem->Attribute("id");
			if(getLight(lightid) != NULL)
			{
				printf("light id already exists: %s", lightid.c_str());
				return false;
			}

			elem->QueryIntAttribute("enabled",&on);
			
			float location[4];
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "location"){
				
						subelem->QueryFloatAttribute("x",&location[0]);
						subelem->QueryFloatAttribute("y",&location[1]);
						subelem->QueryFloatAttribute("z",&location[2]);
						subelem->QueryFloatAttribute("w",&location[3]);
					
				}
				else if (subelem->ValueTStr() == "ambient"){
					
						subelem->QueryFloatAttribute("r",&ambient[0]);
						subelem->QueryFloatAttribute("g",&ambient[1]);
						subelem->QueryFloatAttribute("b",&ambient[2]);
						subelem->QueryFloatAttribute("a",&ambient[3]);
					
				}
				else if (subelem->ValueTStr() == "diffuse"){
					
						subelem->QueryFloatAttribute("r",&diffuse[0]); 
						subelem->QueryFloatAttribute("g",&diffuse[1]); 
						subelem->QueryFloatAttribute("b",&diffuse[2]); 
						subelem->QueryFloatAttribute("a",&diffuse[3]); 
					
				}
				else if (subelem->ValueTStr() == "specular"){
				
						subelem->QueryFloatAttribute("r",&specular[0]); 
						subelem->QueryFloatAttribute("g",&specular[1]); 
						subelem->QueryFloatAttribute("b",&specular[2]); 
						subelem->QueryFloatAttribute("a",&specular[3]); 
					
				}
			}
	
			OmniL *omni= new OmniL(location,ambient,diffuse,specular,on,lightX++);
			lights[lightid]=omni;

		}
		else if( elem->ValueTStr() == "spot"){

			float location[3],target[3],angle, exponent;

			string lightid= elem->Attribute("id");
			if(getLight(lightid) != NULL)
			{
				printf("light id already exists: %s", lightid.c_str());
				return false;
			}
			elem->QueryIntAttribute("enabled",&on); 
			elem->QueryFloatAttribute("angle",&angle);
			elem->QueryFloatAttribute("exponent",&exponent);
						
			for(TiXmlElement *subelem(elem->FirstChildElement()); subelem != NULL; subelem = subelem->NextSiblingElement())
			{
				if(subelem->ValueTStr() == "location"){
				
						subelem->QueryFloatAttribute("x",&location[0]);
						subelem->QueryFloatAttribute("y",&location[1]);
						subelem->QueryFloatAttribute("z",&location[2]);
				
				}
				else if (subelem->ValueTStr() == "ambient"){
				
						subelem->QueryFloatAttribute("r",&ambient[0]); 
						subelem->QueryFloatAttribute("g",&ambient[1]); 
						subelem->QueryFloatAttribute("b",&ambient[2]); 
						subelem->QueryFloatAttribute("a",&ambient[3]); 
					
				}
				else if (subelem->ValueTStr() == "diffuse"){
					
						subelem->QueryFloatAttribute("r",&diffuse[0]); 
						subelem->QueryFloatAttribute("g",&diffuse[1]); 
						subelem->QueryFloatAttribute("b",&diffuse[2]); 
						subelem->QueryFloatAttribute("a",&diffuse[3]); 
					
				}
				else if (subelem->ValueTStr() == "specular"){
					
						subelem->QueryFloatAttribute("r",&specular[0]); 
						subelem->QueryFloatAttribute("g",&specular[1]); 
						subelem->QueryFloatAttribute("b",&specular[2]); 
						subelem->QueryFloatAttribute("a",&specular[3]);
					
				}
				else if (subelem->ValueTStr() == "target"){
					
						subelem->QueryFloatAttribute("x",&target[0]); 
						subelem->QueryFloatAttribute("y",&target[1]); 
						subelem->QueryFloatAttribute("z",&target[2]); 
					
				}	  
			}

			SpotL *spotl = new SpotL(location,target,angle,exponent,ambient,diffuse,specular,on,lightX++);
			lights[lightid]=spotl;
		}

	}
	nlights=lightX;
	return true;
}

Light* SceneLoader::getLight( string id )
{
	map<string,Light*>::iterator it = lights.find(id);

	if(it==lights.end())
		return NULL;
	else
		return it->second;
}

void SceneLoader::cycleLights()
{
	for(map<string,Light*>::iterator it=lights.begin(); it != lights.end(); ++it)
		it->second->act();
}

void SceneLoader::changeMatByKey( char c)
{
	Component *comp = getMultMats(c);

	if(comp != NULL)
		comp->nextMat();
}

int SceneLoader::getNumberOfLights(){
	return nlights;
}

pair<string,Light*> SceneLoader::getLightByIndex( int i )
{
	int j=0;
	for(map<string,Light*>::iterator it=lights.begin(); it != lights.end(); ++it)
		if(j==i)
			return *it;
		else
			++j;
}

pair<string,View*> SceneLoader::getViewByIndex( int i )
{
	int j=0;
	for(map<string,View*>::iterator it=views.begin(); it != views.end(); ++it)
		if(j==i)
			return *it;
		else
			++j;
}

int SceneLoader::getNumberOfViews()
{
	return views.size();
}

void SceneLoader::setCurrentViewIDbyIndex( int d )
{
	int j=0;
	for(map<string,View*>::iterator it=views.begin(); it != views.end(); ++it)
		if(j==d){
			setCurrentViewID(it->first);
			break;
		}
		else
			++j;
}

void SceneLoader::getLightAttenuation( int atten )
{
	int v[] = {0,0,0};
	if(atten)
		v[1]=1;
	else
		v[0]=1;

	for(map<string,Light*>::iterator it=lights.begin(); it != lights.end(); ++it)
		it->second->setAttenuation(v);
}
